#include <iostream>
#include <memory>

// 定义一些常量
const int TRUE = 1;
const int FALSE = 0;
const int OK = 1;
const int ERROR = 0;
const int OVERFLOW = -1;

// 类型定义
using Status = int;
using ElemType = int;

// 测试程序长度定义
const int LENGTH = 5;

// 链表节点类
struct LNode {
    ElemType data;
    std::shared_ptr<LNode> next;

    // 构造函数
    LNode(ElemType d, std::shared_ptr<LNode> n = nullptr) : data(d), next(n) {}
};

// 链表类，具有头结点
class LinkList {
public:
    // 构造函数，初始化头节点
    LinkList() : head(std::make_shared<LNode>(0)) {}

    // 创建包含 n 个元素的链表，元素值存储在 data 数组中
    Status create(const ElemType* data, int n) {
        if (n < 0) return ERROR;

        auto p = head; // 初始化为头结点
        for (int i = 0; i < n; i++) {
            auto q = std::make_shared<LNode>(data[i]);
            if (!q) return OVERFLOW;
            p->next = q;
            p = q;
        }
        return OK;
    }

    // 从链表末尾入链表
    Status EnQueue(ElemType e) {
        auto q = std::make_shared<LNode>(e);
        if (!q) return OVERFLOW;

        auto p = head;
        while (p->next) {
            p = p->next;
        }
        p->next = q;
        return OK;
    }

    // 从链表头节点出链表
    Status DeQueue(ElemType &e) {
        if (!head->next) return ERROR; // 链表为空

        auto p = head->next;
        e = p->data;
        head->next = p->next; // 删除节点
        return OK;
    }

    // 遍历单链表并调用访问函数
    void ListTraverse(Status(*visit)(ElemType e)) const {
        if (!head->next) return;

        auto p = head->next;
        while (p) {
            visit(p->data);
            p = p->next;
        }
    }

private:
    std::shared_ptr<LNode> head; // 链表头指针，包含头结点
};

// 访问函数
Status visit(ElemType e) {
    std::cout << e << "\t";
    return OK;
}

int main() {
    ElemType e, data[LENGTH] = { 1, 2, 3, 4, 5 };
    LinkList L;

    // 显示测试值
    std::cout << "---【有头结点的单链表】---" << std::endl;
    std::cout << "待测试元素为：" << std::endl;
    for (int i = 0; i < LENGTH; i++) std::cout << data[i] << "\t";
    std::cout << std::endl;

    // 创建链表L
    std::cout << "创建链表L" << std::endl;
    if (ERROR == L.create(data, LENGTH)) {
        std::cout << "创建链表L失败" << std::endl;
        return -1;
    }
    std::cout << "成功创建包含1个头结点、" << LENGTH << "个元素的链表L" << std::endl;

    // 遍历单链表
    std::cout << "此时链表中元素为：" << std::endl;
    L.ListTraverse(visit);
    std::cout << std::endl;

    // 从链表头节点出链表到e
    std::cout << "\n出链表到e" << std::endl;
    L.DeQueue(e);
    std::cout << "出链表的元素为：" << e << std::endl;
    std::cout << "此时链表中元素为：" << std::endl;
    L.ListTraverse(visit);
    std::cout << std::endl;

    // e从链表末尾入链表
    std::cout << "\ne入链表" << std::endl;
    L.EnQueue(e);
    std::cout << "入链表的元素为：" << e << std::endl;
    std::cout << "此时链表中元素为：" << std::endl;
    L.ListTraverse(visit);
    std::cout << std::endl;

    return 0;
}
